package security.config;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import security.filter.VerificationCodeFilter;
import security.mobile.MobileAuthenticationSecurityConfig;
import security.service.MyUserDetailsService;
import security.session.MyExpiredSessionStrategy;

/**
 * security配置
 * @author majie
 *
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter{
	
	@Autowired
	private MobileAuthenticationSecurityConfig mobileAuthenticationSecurityConfig;
	
	@Autowired
	private VerificationCodeFilter verificationCodeFilter;
	
	@Autowired
	private MyUserDetailsService myUserDetailsService;
	
	@Autowired
	private DataSource dataSource;
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http
			.addFilterBefore(verificationCodeFilter, UsernamePasswordAuthenticationFilter.class)   //在认证账户密码之前认真验证码
			.apply(mobileAuthenticationSecurityConfig)
				.and()
			.formLogin()								//表单登陆
				.loginPage("/login/authentication")			//指定需要登录时发送用户的URL，根据需要重定向请求，需要自己写对应的请求路径
				.loginProcessingUrl("/login/form")			//指定验证凭据的URL，和表单路径一样
				.and()
			.authorizeRequests()
				.antMatchers("/login.html","/login/authentication","/session/invalid","/session/max")
				.permitAll()								//上面匹配的请求允许访问
				.anyRequest()
				.authenticated()							//其他请求不允许访问
				.and()	
			.rememberMe()
				.userDetailsService(myUserDetailsService)
				.tokenRepository(persistentTokenRepository())
				.tokenValiditySeconds(3600)     //设置token过期时间
				.and()
			.sessionManagement()
				.invalidSessionUrl("/session/invalid")   //无效session跳转的路径，该地址需要添加到授权控制里面
				.maximumSessions(1)						//最大并发登录
				.expiredSessionStrategy(new MyExpiredSessionStrategy())   //session过期时候的策略
				.maxSessionsPreventsLogin(true)    //达到最大并发登陆以后阻止其他登陆
				.and()
				.and()
			.logout()
				.logoutUrl("/logout")    //登出路径
				.logoutSuccessUrl("/login.html")    //登出成功跳转到登陆页面
				.deleteCookies("JSESSIONID")		//删除cookie
				.and()
			.csrf().disable();
	}
	
	@Bean
	public PersistentTokenRepository persistentTokenRepository() {
		JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
		tokenRepository.setDataSource(dataSource);
//		tokenRepository.setCreateTableOnStartup(true);   //首次设置为true,自动创建表，如果这里不设置为true就需要自己手动创建表
		return tokenRepository;
	}
}
